package com.thinkit.core.aspect;
import cn.hutool.core.util.EnumUtil;
import com.thinkit.core.annotation.SiteMark;
import com.thinkit.core.base.BaseContextKit;
import com.thinkit.core.handler.CustomException;
import com.thinkit.utils.enums.SiteOperation;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.model.BaseDto;
import com.thinkit.utils.model.PageDto;
import com.thinkit.utils.utils.Checker;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;

@Aspect
@Component
public class SiteAspect {

    @Pointcut("execution(* com.thinkit.*..*.*(..)) && @annotation(com.thinkit.core.annotation.SiteMark)")
    public void declareJoinPointerExpression() {
    }


    @Around("declareJoinPointerExpression()")
    public Object checkSite(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        String siteId = BaseContextKit.getSiteId();
        SiteMark siteMark = method.getAnnotation(SiteMark.class);
        if(EnumUtil.equals(siteMark.type(), SiteOperation.WRITE.name())){
            if (Checker.BeBlank(siteId)) {
                throw new CustomException(ApiResult.result(5022));
            }
            setSiteId(pjp.getArgs(),siteId);
        }else if(EnumUtil.equals(siteMark.type(), SiteOperation.READ.name())){
            if(Checker.BeBlank(siteId)){
                siteId = "-1";
            }
            setSiteId(pjp.getArgs(),siteId);
        }
        return pjp.proceed();
    }

    private void setSiteId(Object[] args,String siteId){
         if(Checker.BeNotEmpty(args)){
             for(Object object:args){
                 if(object instanceof BaseDto){
                     setBaseDtoSite(object,siteId);
                 }else if(object instanceof PageDto){
                     setPageDtoSite(object,siteId);
                 }else if(object instanceof List){
                     loopSetSiteId(object,siteId);
                 }
             }
         }
    }

    private void setBaseDtoSite(Object object,String siteId){
        BaseDto dto = (BaseDto) object;
        dto.setSiteId(siteId);
    }

    private void setPageDtoSite(Object object,String siteId){
        PageDto pageDto = (PageDto) object;
        if(pageDto.getDto() instanceof  BaseDto && Checker.BeNotNull(pageDto.getDto())){
            BaseDto dto = (BaseDto) pageDto.getDto();
            if(Checker.BeBlank(dto.getSiteId())){
                dto.setSiteId(siteId);
            }
        }
    }

    private void loopSetSiteId(Object os,String siteId){
        List list =(List) os;
        if(Checker.BeNotEmpty(list)){
            for(Object o :list){
                if(o instanceof  BaseDto && Checker.BeNotNull(o)){
                    ((BaseDto) o).setSiteId(siteId);
                }
            }
        }
    }
}
